// CS251 Data Structures
// String Implementation
// IMPORTANT: Do not use any of the functions in the string C runtime library
// Example. Do not use strcpy, strcmp, etc. Implement your own

// IMPORTANT: See the MyString.h file for a description of
// what each method needs to do.

#include <stdio.h>
#include <stdlib.h>
#include "MyString.h"

// My own implementation of strlen
int MyString::slength(const char *s) const {
	int count = 0;
	while (s[count] != 0) {
		count++;
	}
	return count;
}

// Initialize _s. Allocate memory for _s and copy s into _s
void MyString::initialize(const char * s) {
	// Add implementation here
	// Allocate memory for _s.
	_s = (char*)malloc(sizeof(s));
	// Copy s into _s
	for (int idx = 0; idx < slength(s); idx++)
		_s[idx] = s[idx];
}

// Create a MyString from a C string
MyString::MyString(const char * s) {
	initialize(s);
}

// Create a MyString from a copy of another string
MyString::MyString(const MyString &s) {
	initialize(s._s);
}

// Create a MyString with an empty string
MyString::MyString() {
	_s = new char[1];
	*_s = 0;
}

// Assignment operator. Without this operator the assignment is
// just a shallow copy that will copy the pointer _s. If the original _s
// goes away then the assigned _s will be a dangling reference.
MyString &
MyString::operator =(const MyString & other) {
	if (this != &other) // protect against invalid self-assignment
	{
		// deallocate old memory
		delete[] _s;

		// Initialize _s with the "other" object.
		initialize(other._s);

		// by convention, always return *this
		return *this;
	}
	return *this;
}

// Obtain a substring of at most n chars starting at location i
// if i is larger than the length of the string return an empty string.
MyString MyString::substring(int i, int n) {
	// Add implementation here
	if (i > slength(_s) || i < 0)
		return *new MyString();
	// Make sure that i is not beyond the end of string
	// Allocate memory for substring
	char *substr = (char*)malloc(n*sizeof(char) + 1);
	// Copy characters of substring
	for (int idx = i; idx < i + n; idx++)
		substr[idx-i] = _s[idx];
	substr[n+1] = 0;
	MyString sub = *new MyString(substr);
	// Return substring
	return sub;
}

// Remove at most n chars starting at location i
void MyString::remove(int i, int n) {
	// Add implementation here
	int sum;
	char *p = _s;
	if (i + n > slength(_s))
		sum = slength(_s);
	else
		sum = i + n;
	for (int idx = i; idx < sum; idx++)
		p[idx] = p[idx + sum];
	p[sum+1] = 0;
	for (int idx = sum; idx < slength(_s); idx++)
		p[idx] = 0;
	return;
	// If i is beyond the end of string return

	// If i+n is beyond the end trunc string

	// Remove characters
}

// Return true if strings "this" and s are equal
bool MyString::operator ==(const MyString & s) {
	if (slength(_s) != s.length())
		return false;
	char *t0;
	char *t1;
	t0 = _s;
	t1 = s._s;
	while (t0 != 0) {
		if (t0 != t1)
			return false;
		t0++; t1++;
	}
	return true;
}

// Return true if strings "this" and s are not equal
bool MyString::operator !=(const MyString &s) {
	if (slength(_s) != s.length())
		return true;
	char *t0 = _s;
	const char *t1 = s._s;
	while (t0 != 0) {
		if (t0 != t1)
			return true;
		t0++; t1++;
	}
	return false;
}

// Return true if string "this" and s is less or equal
bool MyString::operator <=(const MyString &s) {
	char *t0 = this->_s;
	const char *t1 = s._s;
	while (t0 != 0 && t1 != 0) {
		if (t0 < t1)
			return true;
		t0++; t1++;
	}
	if (slength(_s) != s.length())
		return false;
	t0 = _s;
	t1 = s._s;
	while (t0 != 0) {
		if (t0 != t1)
			return false;
		t0++; t1++;
	}
	return false;
}

// Return true if string "this" is greater than s
bool MyString::operator >(const MyString &s) {
	char *t0 = this->_s;
	const char *t1 = s._s;
	while (t0 != 0 && t1 != 0) {
		if (t0 > t1)
			return true;
		t0++; t1++;
	}
	return false;
}

// Return character at position i.  Return '\0' if out of bounds.
char MyString::operator [](int i) {
	if (i < 0 || (unsigned int)i > sizeof(_s)/sizeof(char))
		return 0;
	return _s[i];
}

// Return C representation of string
const char *
MyString::cStr() {
	// Add implementation here
	return _s;
}

// Get string length of this string.
int MyString::length() const {
	// Add implementation here
	return slength(_s);
}

// Destructor. Deallocate the space used by _s
MyString::~MyString() {
	// Add implementation here
	delete[] _s;
}

// Concatanate two strings (non member method)
MyString operator +(const MyString &s1, const MyString &s2) {
	// Add implementation here

	// Allocate memory for the concatenated string

	// Add s1

	// Add s2

	MyString s;
	return s;
}

